using System;
using System.Web;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Collections;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Security.Cryptography;
using ICSharpCode.SharpZipLib.GZip;
using System.Reflection;
using System.Web.Caching;


namespace ACM.cmsarea08.Controls
{
	public enum LoadModuleSelector {
		control,
		body
	}
	public class SingleModuleItem :IAttributeAccessor {
		private string _path ;
		private string _istid ;
		private string _name ;
		private string _cid ;
		private string _cpid ;
		private string _html;
		private LoadModuleSelector _lm = LoadModuleSelector.control;
		private System.Web.UI.AttributeCollection attrColl;
        private StateBag attrState;
        public System.Web.UI.AttributeCollection Attributes
        {
            get
            {
                if (this.attrColl == null)
                {
                    if (this.attrState == null)
                    {
                        this.attrState = new StateBag(true);

                    }
                    this.attrColl = new System.Web.UI.AttributeCollection(this.attrState);
                }
                return this.attrColl;
            }
        }
        string IAttributeAccessor.GetAttribute(string name)
        {
            if (this.attrState == null)
                return null;
            else
                return (string)this.attrState[name];
        }
        void IAttributeAccessor.SetAttribute(string name, string value)
        {
            this.Attributes[name] = value;
        }

        public LoadModuleSelector LoadModuleControl {
        	get {
        		return _lm;
        	}
        	set {
        		_lm = value;
        	}
        }
		
        
		public string InstanceID {
			get { return _istid;}
			set {_istid = value;}
		}
		public string ControlID {
			get { return _cid;}
			set {_cid = value;}
		}
		
		public string Path {
			get { return _path;}
			set {_path = value;}
		}
		public string Html {
			get { return _html;}
			set {_html = value;}
		}
		
		public string Name {
			get { return _name;}
			set {_name = value;}
		}
		public string ComponentName {
			get { return _cpid;}
			set {_cpid = value;}
		}
		
		public override string ToString()
		{
			return InstanceID;
		}
		public bool isValid() {
			bool valid= false;
			if(string.IsNullOrEmpty(InstanceID)) valid= false;
			if(!string.IsNullOrEmpty(_html)) valid=true;
			return valid;			
		}
		
		
	}
	
	[ToolboxData("<{0}:Itan_ViewBlock runat=server Name=''></{0}:Itan_ViewBlock>"),ParseChildren(true)]
	public class Itan_ViewBlock : Control
    {
		 private List<SingleModuleItem> _singleItem = new List<SingleModuleItem>(); 
		 private string _nome;
        
        [Bindable(true),
		 Browsable (true),
         Category("Appearance"),
         Description("Get/Set ViewBlock Name"),
         DefaultValue("")]
		public string Name
        {
            get
            {
                return _nome;
            }
            set
            {
                _nome = value;
            }
        }
		

 		[NotifyParentProperty(true)] 
        [PersistenceMode(PersistenceMode.InnerProperty)] 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        public List<SingleModuleItem> SingleItems 
        { 
            get { return _singleItem; } 
        } 
        
        
		private object CountModuli{
			get {
				object o = this.getCacheObject(this.ID + "_ModuleCount");
				if(o==null) {
					return null;
				}
				else {
					return o;
				}
			}
			set {
				//ViewState[this.ID + "_ModuleCount"]= value;
				this.setCacheObject(this.ID + "_ModuleCount", value,180);
			}
		}
		
		private DataSet ModuleList {
			get {

				object o = this.getCacheObject(this.ID + "_moduleList");
				if(o!=null) {
					return (DataSet)o;
				}else {
					return null;
				}
			}
			set {
				if(value==null) return;
				this.setCacheObject(this.ID + "_moduleList", value,180);
			}
		}
      
        public Itan_ViewBlock() : base()   {
        	//inizializzatore Classe
        	_nome = "";
         }
 			
		override protected void OnInit(EventArgs e)
		{
			bool valid = false;
			if(this.SingleItems!=null) {
				for(int i= 0;i<SingleItems.Count;i++) {
					if(!SingleItems[i].isValid()) {
						break;
					}
					valid =SingleItems[i].isValid();
					//HttpContext.Current.Response.Write("<br/>cc["+i+"]: " + this.SingleItems[i].Name);
				}
			}
			if(valid) {
				LoadItems();
			} else {
				LoadBlocks();
			}
			InitializeComponent();
			base.OnInit(e);		
		}

		private void LoadBlocks() {
			if(Name.Trim()=="")
				return;
            string CurrentLanguage = "";
            if (this.Page is ACM.cmsarea08.Core.MainPage)
            {
                CurrentLanguage = ((ACM.cmsarea08.Core.MainPage)this.Page).Page_Lang;
            }
            else
           { 
                if (ACM.cmsarea08.Users.CurrentUser != null)
                {
                    if (ACM.cmsarea08.Users.CurrentUser.Autorizzato && ACM.cmsarea08.Users.CurrentUser.PrefLanguage != "")
                        CurrentLanguage = ACM.cmsarea08.Users.CurrentUser.PrefLanguage;
                    else
                        CurrentLanguage = ACM.cmsarea08.mainconfiguration.MainConf.LinguaPredefinita;
                }
                else
                {
                    CurrentLanguage = ACM.cmsarea08.mainconfiguration.MainConf.LinguaPredefinita;
                }
            }
			ACM.cmsarea08.Function.TextClass tcl = new ACM.cmsarea08.Function.TextClass();
			
			string basePT = ACM.cmsarea08.mainconfiguration.MainConf.PrefissoTabelle;
			object contoModuli = CountModuli;
			if(contoModuli==null) {
				contoModuli = ACM.cmsarea08.DBManager.mainConnection.HStandard_SC(
					" SELECT count(*) FROM "+basePT+"moduli where " + 
					" blocco_visivo = " +
					" (select id from "+basePT+"blocco_visivo where titolo='"+tcl.SqlTesto(Name.Trim())+"' and enabled='1' limit 1)" +
	                " and enabled ='1' and locate('" + CurrentLanguage + "',if(languages='','" + CurrentLanguage + "',languages))>0 ;");
			} 
			
			if(contoModuli==null)
				return;
			if(contoModuli.ToString()=="0")
				return;
			if(this.CountModuli!= contoModuli) {
				ModuleList = null;
			}
			CountModuli = contoModuli;
			if(ModuleList==null) {
				ModuleList = ACM.cmsarea08.DBManager.mainConnection.Helper_Dataset(
				" SELECT id,titolo, visible_home, parametri, " +
				"(select url_path from "+basePT+"componenti where id = id_componente) as mod_path,  " +
				"(select blockview_control from "+basePT+"componenti where id = id_componente) as ascx_mod  " +
				" FROM "+basePT+"moduli where " +
				" blocco_visivo = " +
				" (select id from "+basePT+"blocco_visivo where titolo='"+tcl.SqlTesto(Name.Trim())+"' and enabled='1' limit 1) " +
                " and enabled ='1' and locate('" + CurrentLanguage + "',if(languages='','" + CurrentLanguage + "',languages))>0 " +
                "  order by ordine asc; ");
                //ModuleList = ACM.cmsarea08.DBManager.mainConnection.Helper_Dataset(
                //                    " SELECT id,titolo,parametri, visible_home, mdaddons,  " +
                //"(select url_path from " + basePT + "componenti where id = id_componente) as mod_path,  " +
                //"(select blockview_control from " + basePT + "componenti where id = id_componente) as ascx_mod,  " +
                //"(select addons from " + basePT + "componenti where id = id_componente) as srcaddons  " +
                //" FROM " + basePT + "moduli where " +
                //" blocco_visivo = " +
                //" (select id from " + basePT + "blocco_visivo where titolo='" + tcl.SqlTesto(Name.Trim()) + "' limit 1) " +
                //" and enabled ='1' and locate('" + CurrentLanguage + "',if(languages='','" + CurrentLanguage + "',languages))>0 " +
                //" order by ordine asc;");

			}
			if(ModuleList==null) {
				this.Visible=false;
//				HttpContext.Current.Response.Write("<hr/>"+Name+">QUESTO BLOCCO "+Name+", non ha moduli assegnati<br/>");
				return;
			}
			ArrayList a = new ArrayList();
            bool isHomepage = false;
            if (this.Page is ACM.cmsarea08.Core.MainPage)
            {
                isHomepage = ((ACM.cmsarea08.Core.MainPage)this.Page).IsHomePage;
            }			
			for(int i = 0 ; i<ModuleList.Tables[0].Rows.Count;i++) {
				DataRow dr = ModuleList.Tables[0].Rows[i];
//				HttpContext.Current.Response.Write("<hr/>"+Name+">SONO IL MODULO: " +dr["mod_path"].ToString()+ ",: " +dr["id"].ToString() +"<br/>");
				string path = CheckModule(dr["mod_path"].ToString(),dr["ascx_mod"].ToString());
				
				if(path==string.Empty) {
//					HttpContext.Current.Response.Write(""+Name+">SONO NULLO[CHECK PATH]: " + dr["mod_path"].ToString()+"/"+dr["ascx_mod"].ToString()+"<br/>");
					continue;
				}
					
				else {
					try {
                        //HttpContext.Current.Response.Write(this.Name + "SONO IN P: " + isHomepage + ".. " + dr["visible_home"] + 
                        //    "CONDIZIONE : " + (( isHomepage && dr["visible_home"].ToString() == "2") || (!isHomepage && dr["visible_home"].ToString() == "1")) + 
                        //    "<br/>");
                        if (( isHomepage && dr["visible_home"].ToString() == "2") || (!isHomepage && dr["visible_home"].ToString() == "1")) {
//                        	HttpContext.Current.Response.Write(""+Name+">SONO NULLO[CHECK HOMEVISUS]: HP_:" + isHomepage+"; VISIBLE_HOME: "+dr["visible_home"].ToString()+"<br/>");
							continue;
                        }

	                	string para = string.Empty;
	                	if(dr["parametri"]!=null) {
		                	if(dr["parametri"]is byte[])
		                		para = System.Text.Encoding.UTF8.GetString((byte[])dr["parametri"]);
		                	else
		                		para = dr["parametri"].ToString();
	                	}                        
						ACM.cmsarea08.Controls.Itan_BaseComponent c = (ACM.cmsarea08.Controls.Itan_BaseComponent)this.Page.LoadControl(path);
						c.Name = dr["titolo"].ToString();
						c.InstanceID = dr["id"].ToString();
						c.setParameter(para);
						//c.SetParameters(dr["parametri"]);
                        //c.SetAddons(dr["mdaddons"], dr["srcaddons"]);
						a.Add(c);
					}catch (Exception exception) {
						//ERRORE
                        HttpContext.Current.Response.Write(""+Name+">LOAD ERRORE ER: " + exception.ToString()); 
                    }
				}
				//this.Controls.Add(new LiteralControl("<div>Controllo: " + dr["titolo"] + "--> PAth: " +  + "</div>"));
			}
			
			if(a.Count==0)
				this.Visible=false;
			else {
				this.Visible=true;
				foreach(Itan_BaseComponent c in a) 
					this.Controls.Add(c);
			}
			
		}
		private void LoadItems() {
			if(SingleItems.Count==0)
				return;
            string CurrentLanguage = "";
            if (this.Page is ACM.cmsarea08.Core.MainPage)
            {
                CurrentLanguage = ((ACM.cmsarea08.Core.MainPage)this.Page).Page_Lang;
            }
            else
           { 
                if (ACM.cmsarea08.Users.CurrentUser != null)
                {
                    if (ACM.cmsarea08.Users.CurrentUser.Autorizzato && ACM.cmsarea08.Users.CurrentUser.PrefLanguage != "")
                        CurrentLanguage = ACM.cmsarea08.Users.CurrentUser.PrefLanguage;
                    else
                        CurrentLanguage = ACM.cmsarea08.mainconfiguration.MainConf.LinguaPredefinita;
                }
                else
                {
                    CurrentLanguage = ACM.cmsarea08.mainconfiguration.MainConf.LinguaPredefinita;
                }
            }
			ACM.cmsarea08.Function.TextClass tcl = new ACM.cmsarea08.Function.TextClass();
			
			string basePT = ACM.cmsarea08.mainconfiguration.MainConf.PrefissoTabelle;
			object contoModuli = CountModuli;
			if(contoModuli==null) {
				contoModuli = SingleItems.Count;
			} 
			if(contoModuli==null)
				return;
			if(contoModuli.ToString()=="0")
				return;
			if(this.CountModuli!= contoModuli) {
				ModuleList = null;
			}
			CountModuli = contoModuli;
			
			
			if(ModuleList==null) {
				//deve verificare se ho path, titolo e parametri. altrimenti li legge e li setta.
				
				
				//string elencoId ="";
				string _select="";
				string[] querys = new string[SingleItems.Count];
				for(int i=0;i<SingleItems.Count;i++) {
					if(!string.IsNullOrEmpty(SingleItems[i].Html)) {
						querys[i]= "SELECT '0' as id,'literal' as titolo, '1' as visible_home, 'html' as parametri,  " +
						"'' as mod_path, '' as ascx_mod, '' body_mod, " +
						"" + i + " as myorder"; continue;
					}
					querys[i] = "SELECT modi.id,modi.titolo, modi.visible_home, modi.parametri,  " +
						"comp.url_path as mod_path, comp.blockview_control as ascx_mod, mainbody_control as body_mod, " +
						"" + i + " as myorder "+
						" FROM "+basePT+"moduli as modi " +
						"left join "+basePT+"componenti as comp on comp.id = modi.id_componente  " +
						"where modi.id = " + SingleItems[i].InstanceID + " ";
				}
				
				if(querys.Length>1) {
					_select = "(" + string.Join(") UNION (",querys) + ") ";
				} else {
					_select = querys[0];
				}
				
				_select += " order by myorder asc;";
//				HttpContext.Current.Response.Write(_select);
				ModuleList = ACM.cmsarea08.DBManager.mainConnection.Helper_Dataset(_select);
			}
			if(ModuleList==null) {
				this.Visible=false;
				return;
			}
			ArrayList a = new ArrayList();
            bool isHomepage = false;
            if (this.Page is ACM.cmsarea08.Core.MainPage)
            {
                isHomepage = ((ACM.cmsarea08.Core.MainPage)this.Page).IsHomePage;
            }			
			for(int i = 0 ; i<ModuleList.Tables[0].Rows.Count;i++) {
				DataRow dr = ModuleList.Tables[0].Rows[i];
				
				if(dr["titolo"].ToString()=="literal" &&
				   dr["parametri"].ToString()=="html" ) {
					//sono di fronte a un xml literal
					LiteralControl cc = new LiteralControl(SingleItems[i].Html);
					a.Add(cc);
					continue;
				}
				string path = CheckModule(dr["mod_path"].ToString(),
				                          (SingleItems[i].LoadModuleControl== LoadModuleSelector.control?dr["ascx_mod"].ToString():dr["body_mod"].ToString())
				                         );
//				HttpContext.Current.Response.Write(path);
				
				if(path==string.Empty) {
					continue;
				}
				else {
					try {
	                	string para = string.Empty;
	                	if(dr["parametri"]!=null) {
		                	if(dr["parametri"]is byte[])
		                		para = System.Text.Encoding.UTF8.GetString((byte[])dr["parametri"]);
		                	else
		                		para = dr["parametri"].ToString();
	                	}                        
						ACM.cmsarea08.Controls.Itan_BaseComponent c = (ACM.cmsarea08.Controls.Itan_BaseComponent)this.Page.LoadControl(path);
						c.Name = dr["titolo"].ToString();
						c.InstanceID = dr["id"].ToString();
						if(!string.IsNullOrEmpty(SingleItems[i].ControlID)) 
							c.ID = SingleItems[i].ControlID;
						//verifica dei parametri e slit per ~ e poi per =
						string[] parametri = new string[0];
						if(SingleItems[i].Attributes.Count>0) {
	                        foreach (object key in SingleItems[i].Attributes.Keys)
	                        {
	                            String _key = (String)key;
	                            this.trySetCustomParameters(c, _key, SingleItems[i].Attributes[_key]);
	                            //c.Attributes.Add(_key,SingleItems[i].Attributes[_key]);
//                       			HttpContext.Current.Response.Write("Metto Param:"+_key+"["+SingleItems[i].Attributes[_key]+"]<br/>");
	                            
	                        }
						}
//                       	HttpContext.Current.Response.Write(""+c.Name+" - Aggiungo Controllo :<br/>");
						c.setParameter(para);
						//c.SetParameters(dr["parametri"]);
                        //c.SetAddons(dr["mdaddons"], dr["srcaddons"]);
						a.Add(c);
					}catch (Exception exception) {
						//ERRORE
                        HttpContext.Current.Response.Write(""+Name+">LOAD ERRORE ER: " + exception.ToString()); 
                    }
				}
				//this.Controls.Add(new LiteralControl("<div>Controllo: " + dr["titolo"] + "--> PAth: " +  + "</div>"));
			}
			
			if(a.Count==0)
				this.Visible=false;
			else {
				this.Visible=true;
				foreach(Itan_BaseComponent c in a) 
					this.Controls.Add(c);
			}
			
		}
		
		private void InitializeComponent()
		{
			//this.Load += new System.EventHandler(this.Page_Load);
		}
	
		
		const string comp_path = "/controls/";
		private string CheckModule(string path,string name)  {
			string ascxPath = comp_path + path + "/" + name;
			if( System.IO.File.Exists(HttpContext.Current.Server.MapPath(ascxPath)) )
				return ascxPath;
			else
				return string.Empty;
		}

        public void setCacheObject(string key, object value)
        {
        	if(value==null) return;
            if (this.Page.Cache[key] != null)
                this.Page.Cache.Remove(key);
            this.Page.Cache.Insert(key, value, null, DateTime.Now.AddSeconds(20), System.Web.Caching.Cache.NoSlidingExpiration,
                CacheItemPriority.Normal, null);
        }
        public void setCacheObject(string key, object value, int secondexpire)
        {
        	if(value==null) return;
            if (this.Page.Cache[key] != null)
                this.Page.Cache.Remove(key);
            this.Page.Cache.Insert(key, value, null, DateTime.Now.AddSeconds(secondexpire), System.Web.Caching.Cache.NoSlidingExpiration,
                CacheItemPriority.Normal, null);
        }
        public object getCacheObject(string key)
        {
            if (this.Page.Cache[key] != null)
                return this.Page.Cache[key];
            else
                return null;
        }
		public void LogThis(string message, string source){
        	using(StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory +"\\public\\VIEWBLOCK_log_" + source + ".txt",true))
			{
				sw.WriteLine("------------------ " + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + " ------------------");
				sw.WriteLine("Sorgente: " + source + ";");
				sw.WriteLine("Messaggio: " + message + ";");
				sw.WriteLine("---------------------------------------------------------");
				sw.WriteLine("");
			}
		}

        private void trySetCustomParameters(object istanza, string chiave, string valore)
        {
            Type tipo = istanza.GetType();
            string txtnamespace = tipo.Namespace;
            if(string.IsNullOrEmpty(chiave) )  return;
            if(string.IsNullOrEmpty(valore) )  return;
            if(chiave.Trim().Length==0) return;
            if(valore.Trim().Length==0) return;
//            HttpContext.Current.Response.Write("SONO l'ADDON: " +tipo.ToString());
            MethodInfo method = tipo.GetMethod(chiave.Trim(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
            PropertyInfo membro = tipo.GetProperty(chiave, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
            if (method != null)
            {
                method.Invoke(istanza, new object[] { valore });
            }
            if (membro != null)
            {
//            	HttpContext.Current.Response.Write("SONO IO E DOVREI IMPOSTARE: " +membro.Name);
                try
                {
//            	HttpContext.Current.Response.Write("SONO IO E DOVREI IMPOSTARE: " +membro.Name + " DATO: "+
//                	                                   (membro.PropertyType.BaseType.FullName) + "<br/>");
                	membro.SetValue(istanza, ParserDati(valore,membro.PropertyType), null);
                }
                catch (Exception ex)
                {
                    HttpContext.Current.Response.Write("ERRORE: " + ex.ToString() + "<hr>");
                }
//                HttpContext.Current.Response.Write("DOPO ADD: " + membro.GetValue(istanza,null) + "<hr>");
                
                
            }
        }
        
        private object ParserDati(string valore,Type tipo)
        {
            object valor = null;
            if(tipo==null) return null;
            if(string.IsNullOrEmpty(valore) ) return null;
            if(valore.Trim().Length==0) return null;
//            HttpContext.Current.Response.Write("<br/>VORREI SETTARE:" + tipo);
            switch (tipo.FullName)
            {
                case "System.String":
                    valor= valore;break;
                case "System.Boolean":
                    bool tryB = false;
                    Boolean.TryParse(valore, out tryB);
                    valor= tryB; break;
                case "System.Int16":
                    Int16 try16 = -1;
                    Int16.TryParse(valore, out try16);
                    valor= try16; break;
                case "System.Int32":
                    Int32 try32 = -1;
                    Int32.TryParse(valore, out try32);
                    valor= try32; break;
                case "System.Int64":
                    Int64 try64 = -1;
                    Int64.TryParse(valore, out try64);
                    valor= try64; break;
                case "System.UInt16":
                    UInt16 tryU16 = 0;
                    UInt16.TryParse(valore, out tryU16);
                    valor= tryU16; break;
                case "System.UInt32":
                    UInt32 tryU32 = 0;
                    UInt32.TryParse(valore, out tryU32);
                    valor= tryU32; break;
                case "System.UInt64":
                    UInt64 tryU64 = 0;
                    UInt64.TryParse(valore, out tryU64);
                    valor= tryU64; break;
                case "System.DateTime":
                    DateTime tryD = DateTime.Now;
                    DateTime.TryParse(valore, out tryD);
                    valor= tryD; break;
                case "System.Char":
                    char tryC = ' ';
                    Char.TryParse(valore, out tryC);
                    valor= tryC; break;
                case "System.Decimal":
                    Decimal tryDD = 0;
                    Decimal.TryParse(valore, out tryDD);
                    valor= tryDD; break;
                case "System.Double":
                    Double tryDO = 0;
                    double.TryParse(valore, out tryDO);
                    valor= tryDO; break;
                case "System.Enum":
                    object _v = null;
                    try {_v = System.Enum.Parse(tipo,valore);} catch {_v=null;}
                    valor= _v;break;
                default: 
                    if(tipo.BaseType.FullName.ToLower()=="system.enum") {
	                    object _vD = null;
	                    try {_vD = System.Enum.Parse(tipo,valore);} catch {_vD=null;}
	                    valor= _vD;
                    }
                    break;
            }
            return valor;
        }
		
   }
    

}
